package com.simpleim.codec;

import com.simpleim.common.ProtoInstant;
import com.simpleim.common.exception.InvalidFrameException;
import com.simpleim.im.common.bean.msg.ProtoMsg;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * 简单Protobuf解码器
 */
public class SimpleProtobufDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        in.markReaderIndex();
        if (in.readableBytes() < 8) {
            return;
        }

        // 读取魔数
        int magicCode = in.readShort();
        if (magicCode != ProtoInstant.MAGIC_CODE) {
            String error = "客户端口令不对:" + ctx.channel().remoteAddress();
            throw new InvalidFrameException(error);
        }

        // 读取版本
        in.readShort();
        // 4个字节
        int length = in.readInt();
        // 长度如果小于0，非法数据，关闭连接
        if (length < 0) {
            ctx.close();
            return;
        }

        if (in.readableBytes() < length) {
            in.resetReaderIndex();
            return;
        }

        byte[] contents = new byte[length];
        if (!in.hasArray()) {
            // 直接内存
            in.readBytes(contents, 0, length);
        } else {
            // 浅复制
            ByteBuf slice = in.slice(in.readerIndex(), length);
            contents = slice.array();
        }
        ProtoMsg.Message message = ProtoMsg.Message.parseFrom(contents);
        if (message != null) {
            out.add(message);
        }
    }
}
